package cn.anoxia.springframework.beans.factory.annotation;

import cn.anoxia.springframework.beans.BeanFactory;
import cn.anoxia.springframework.beans.BeansException;
import cn.anoxia.springframework.beans.PropertyValues;
import cn.anoxia.springframework.beans.factory.BeanFactoryAware;
import cn.anoxia.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import cn.anoxia.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import cn.anoxia.springframework.context.annotation.Autowired;
import cn.anoxia.springframework.context.annotation.Qualifier;
import cn.anoxia.springframework.context.annotation.Value;
import cn.anoxia.springframework.utils.ClassUtils;
import cn.hutool.core.bean.BeanUtil;

import java.lang.reflect.Field;

/**
 * The class AutowiredAnnotationBeanPostProcessor.
 * <p>
 * Description:
 *
 * @author: huangle
 * @since: 2021/08/31 19:01
 */
public class AutowiredAnnotationBeanPostProcessor implements InstantiationAwareBeanPostProcessor, BeanFactoryAware {

  private ConfigurableListableBeanFactory beanFactory;

  @Override
  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
  }

  @Override
  public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    return true;
  }

  @Override
  public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    return null;
  }

  @Override
  public PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException {
    Class<?> clazz = bean.getClass();
    clazz = ClassUtils.isCglibProxyClass(clazz) ? clazz.getSuperclass() : clazz;
    Field[] declaredFields = clazz.getDeclaredFields();
    // 获取 @Value注解 参数设置
    for (Field field : declaredFields){
      Value value = field.getAnnotation(Value.class);
      if (value != null){
        String strVal = value.value();
        strVal = beanFactory.resolveEmbeddedValue(strVal);
        BeanUtil.setFieldValue(bean,field.getName(),strVal);
      }
    }
    // 解析@Autowired 导入bean
    for (Field field : declaredFields) {
      Autowired autowiredAnnotation = field.getAnnotation(Autowired.class);
      if (null != autowiredAnnotation) {
        Class<?> fieldType = field.getType();
        String dependentBeanName = null;
        Qualifier qualifierAnnotation = field.getAnnotation(Qualifier.class);
        Object dependentBean = null;
        if (null != qualifierAnnotation) {
          dependentBeanName = qualifierAnnotation.value();
          dependentBean = beanFactory.getBean(dependentBeanName, fieldType);
        } else {
          dependentBean = (Object) beanFactory.getBean(fieldType);
        }
        BeanUtil.setFieldValue(bean, field.getName(), dependentBean);
      }
    }
    return pvs;
  }

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return null;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return null;
  }
}
